import mongoose, { Document, Schema } from 'mongoose';
import bcrypt from 'bcryptjs';
import { hashPassword } from '../utils/password';

export interface IUser extends Document {
  email: string;
  password: string;
  name: string;
  role: 'admin' | 'teacher' | 'student';
  avatar?: string;
  bio?: string;
  lastPasswordChange?: Date;
  passwordHistory?: string[];
  loginAttempts?: number;
  lockUntil?: Date;
  resetPasswordToken?: string;
  resetPasswordExpires?: Date;
  createdAt: Date;
  updatedAt: Date;
  comparePassword(candidatePassword: string): Promise<boolean>;
  isLocked: boolean;
}

const userSchema = new Schema<IUser>({
  email: {
    type: String,
    required: true,
    unique: true,
    lowercase: true,
    trim: true,
  },
  password: {
    type: String,
    required: true,
    minlength: 6,
  },
  name: {
    type: String,
    required: true,
    trim: true,
  },
  role: {
    type: String,
    enum: ['admin', 'teacher', 'student'],
    default: 'teacher',
  },
  avatar: {
    type: String,
    default: '',
  },
  bio: {
    type: String,
    default: '',
  },
  lastPasswordChange: {
    type: Date,
    default: Date.now,
  },
  passwordHistory: [{
    type: String,
  }],
  loginAttempts: {
    type: Number,
    default: 0,
  },
  lockUntil: {
    type: Date,
  },
  resetPasswordToken: {
    type: String,
  },
  resetPasswordExpires: {
    type: Date,
  },
}, {
  timestamps: true,
});

// 账户锁定虚拟属性
userSchema.virtual('isLocked').get(function() {
  return !!(this.lockUntil && this.lockUntil.getTime() > Date.now());
});

// 密码加密中间件
userSchema.pre('save', async function(next) {
  if (!this.isModified('password')) return next();
  
  try {
    // 保存密码历史
    if (this.isModified('password') && !this.isNew) {
      this.passwordHistory = this.passwordHistory || [];
      this.passwordHistory.push(this.password);
      // 只保留最近5个密码
      if (this.passwordHistory.length > 5) {
        this.passwordHistory = this.passwordHistory.slice(-5);
      }
    }
    
    this.password = await hashPassword(this.password);
    this.lastPasswordChange = new Date();
    next();
  } catch (error) {
    next(error as Error);
  }
});

// 比较密码方法
userSchema.methods.comparePassword = async function(candidatePassword: string): Promise<boolean> {
  return bcrypt.compare(candidatePassword, this.password);
};

// 增加登录失败次数
userSchema.methods.incLoginAttempts = function() {
  // 如果已经锁定且锁定时间未过期，重置尝试次数
  if (this.lockUntil && this.lockUntil.getTime() < Date.now()) {
    return this.updateOne({
      $unset: { lockUntil: 1 },
      $set: { loginAttempts: 1 }
    });
  }
  
  const updates: any = { $inc: { loginAttempts: 1 } };
  
  // 达到最大尝试次数后锁定账户
  if (this.loginAttempts + 1 >= 5 && !this.isLocked) {
    updates.$set = { lockUntil: new Date(Date.now() + 2 * 60 * 60 * 1000) }; // 锁定2小时
  }
  
  return this.updateOne(updates);
};

// 重置登录失败次数
userSchema.methods.resetLoginAttempts = function() {
  return this.updateOne({
    $unset: { loginAttempts: 1, lockUntil: 1 }
  });
};

export const User = mongoose.model<IUser>('User', userSchema);